home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Science⁄Math / VideoToolbox / VideoToolboxSources / TranslateLinefeeds.c < prev    next >
Text File  |  1993-12-15  |  7KB  |  193 lines

  1. /*
  2. TranslateLinefeeds.c helps to resolve an incompatibility between code resources
  3. generated by the THINK C compiler that are linked with the MPW stdio library.
  4. The problem is that MPW and THINK C have adopted different solutions to the
  5. problem that Standard C specifies that linefeeds should be represented as '\n'
  6. (normally 10) inside programs, yet Apple, in their wisdom, decided that
  7. linefeeds should be represented by 13 (normally '\r') in Macintosh ASCII text
  8. files. The problem is handled invisibly by both compilers. MPW redefines '\n' to
  9. mean 13. THINK C translates 13 to 10 (and vice versa) when writing and reading
  10. text streams. Unfortunately, when you compile THINK C code resources that call
  11. the MPW stdio library both solutions are eliminated and the old problem raises
  12. its ugly head.
  13.  
  14. TranslateLinefeeds.c intercepts the calls to the (MPW) stdio library and partially
  15. implements the THINK C stdio library convention of translating \n to \r and vice
  16. versa on input and output to text files. Let's call this "linefeed translation".
  17. (As in the THINK C stdio library, no translation is performed for binary files.)
  18. These routines should only be used by THINK C code resources that must use the
  19. MPW stdio library (because the MPW C stdio library doesn't do linefeed
  20. translation). Don't change your C programs; use the standard names for the stdio
  21. library routines and just #include the TranslateLinefeeds.h header (after stdio.h).
  22. The TranslateLinefeeds.h header uses preprocessor macros to redirect nearly all the
  23. stdio calls to this file, which interposes linefeed translation and calls the
  24. (MPW) stdio library.
  25.  
  26. I've implemented all the i/o routines in stdio.h except fscanf and scanf.
  27. They're difficult to handle, and I suspect that most uses of those routines
  28. wouldn't distinguish /n from /r anyway.
  29.  
  30. All the printf-related routines are funneled through vfprintfTL. The actual
  31. i/o is done by vfprintf(). If it's a "text" stream (as opposed to a "binary"
  32. stream), then we translate the format string before calling vfprintf(), and
  33. translate again afterwards, restoring the original string. This is a pretty good
  34. solution, translating most of the linefeeds, but it fails to translate linefeeds
  35. that appear in string and char arguments.
  36.  
  37. Our implementation of translation is incomplete for printf et al., and
  38. nonexistent for scanf and fscanf because scanning the variable argument list
  39. would require too much effort, requiring us to implement a large fraction of the
  40. printf/scanf code: parsing the format string into tokens, retrieving each
  41. argument, and passing them one at a time to fprintf/scanf.
  42.  
  43. The time overhead of these routines is negligible. All stdio functions that may
  44. be implemented as inline macros are redefined by TranslateLinefeeds.h as new inline
  45. macros that call the original routines.
  46.  
  47. Note that the getchar and putchar macros in TranslateLinefeeds.h assume that stdin
  48. and stdout are "text" streams, though I haven't checked whether this is
  49. guaranteed by Standard C.
  50.  
  51. For debugging, disabling the TRANSLATE flag results in the identity translation, 
  52. making all the code innocuous.
  53.  
  54. HISTORY:
  55. 7/31/93    dgp wrote it.
  56. 7/31/93    dgp Added support for MPW stdio library.
  57. 9/20/93    dgp Rewrote vfprintfTL to work with text strings of unlimited length.
  58.             Documented limitation of the new vfprintfTL. Implemented
  59.             getc, putc, getchar, and putchar as inline macros, in TranslateLinefeeds.h.
  60. */
  61. #include <TranslateLinefeeds.h>
  62. #include <string.h>
  63. #undef fread
  64. #undef fwrite
  65. #undef fgetc
  66. #undef ungetc
  67. #undef fputc
  68. #undef gets
  69. #undef fgets
  70. #undef fputs
  71. #undef vfprintf
  72. #define TRANSLATE 1    /* set this to zero for identity translation, for debugging */
  73.  
  74. unsigned char translateLinefeed[256]={
  75.     #if TRANSLATE
  76.         0,1,2,3,4,5,6,7,8,9,13,11,12,10,14,15,16,17,18,19
  77.     #else
  78.         0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19
  79.     #endif
  80.     ,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39
  81.     ,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59
  82.     ,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79
  83.     ,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99
  84.     ,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119
  85.     ,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139
  86.     ,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159
  87.     ,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179
  88.     ,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199
  89.     ,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219
  90.     ,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
  91.     ,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
  92. };
  93.  
  94. void TranslateLinefeeds(register char *s,register size_t n)
  95. {
  96.     if(s!=NULL)for(;n>0;n--)*s++=translateLinefeed[(unsigned char)*s];
  97. }
  98.  
  99. size_t freadTL(void *s,size_t size,size_t numitems,FILE *stream)
  100. {
  101.     numitems=fread(s,size,numitems,stream);
  102.     if(IS_TEXT(stream))TranslateLinefeeds(s,size*numitems);
  103.     return numitems;
  104. }
  105. size_t fwriteTL(void *s,size_t size,size_t numitems,FILE *stream)
  106. {
  107.     size_t n;
  108.     
  109.     if(IS_TEXT(stream))TranslateLinefeeds(s,size*numitems);
  110.     n=fwrite(s,size,numitems,stream);
  111.     if(IS_TEXT(stream))TranslateLinefeeds(s,size*numitems);
  112.     return n;
  113. }
  114. int fgetcTL(FILE *stream)
  115. {
  116.     char c;
  117.  
  118.     c=fgetc(stream);
  119.     if(IS_TEXT(stream))return translateLinefeed[(unsigned char)c];
  120.     else return c;
  121. }
  122. char *fgetsTL(char *string,int n,FILE *stream)
  123. {
  124.     char *s;
  125.     
  126.     s=fgets(string,n,stream);
  127.     if(IS_TEXT(stream))TranslateLinefeeds(s,strlen(s));
  128.     return s;
  129. }
  130. int fputcTL(int c,FILE *stream)
  131. {
  132.     int i;
  133.  
  134.     if(IS_TEXT(stream))c=translateLinefeed[(unsigned char)c];
  135.     return fputc(c,stream);
  136. }
  137. int fputsTL(char *s,FILE *stream)
  138. {
  139.     int error;
  140.     
  141.     if(IS_TEXT(stream))TranslateLinefeeds(s,strlen(s));
  142.     error=fputs(s,stream);
  143.     if(IS_TEXT(stream))TranslateLinefeeds(s,strlen(s));
  144.     return error;
  145. }
  146. int fprintfTL(FILE *stream,const char *format,...)
  147. {
  148.     va_list args;
  149.     int n;
  150.     
  151.     va_start(args,format);
  152.     n=vfprintfTL(stream,format,args);
  153.     va_end(args);
  154.     return n;
  155. }
  156. char *getsTL(char *string)
  157. {
  158.     char *s;
  159.     
  160.     s=gets(string);
  161.     if(IS_TEXT(stdin))TranslateLinefeeds(s,strlen(s));
  162.     return s;
  163. }
  164. int printfTL(char *format,...)
  165. {
  166.     va_list args;
  167.     int n;
  168.     
  169.     va_start(args,format);
  170.     n=vfprintfTL(stdout,format,args);
  171.     va_end(args);
  172.     return n;
  173. }
  174. /*
  175. In vfprintfTL we only translate the format string. We'll miss linefeeds that
  176. are hiding in char and string arguments in the variable argument list. Finding
  177. those would require a much more elaborate program, which would parse the format
  178. string.
  179. */
  180. int vfprintfTL(FILE *stream,const char *format,va_list args)
  181. {
  182.     int n;
  183.     
  184.     if(IS_TEXT(stream))TranslateLinefeeds((char *)format,strlen((char *)format));
  185.     n=vfprintf(stream,format,args);
  186.     if(IS_TEXT(stream))TranslateLinefeeds((char *)format,strlen((char *)format));
  187.     return n;
  188. }
  189. int vprintfTL(char *format,va_list args)
  190. {
  191.     return vfprintfTL(stdout,format,args);
  192. }
  193.